#include <QtConcurrentMap>
#include <QVector>
#include <QDebug>

#include <qmath.h>

template <typename T>
class Accumulator
{
private:
    T m_sum;

public:
    Accumulator(T const &default_val = T()) : m_sum(default_val) {}
    void add(T const &val) { m_sum += val; }
    T value() const { return m_sum; }
};

template <typename F, typename A>
class Integrate
{
private:
    F m_f;
    A m_min;
    A m_max;
    A m_step;
    A m_init;

public:
    typedef A result_type;

    Integrate(F const &f, A const &min, A const &max, A const &step, A const &init = A())
        : m_f(f)
        , m_min(min)
        , m_max(max)
        , m_step(step)
        , m_init(init)
    {}
    Integrate() {}

    A integrate() const
    {
        A sum = m_init;
        for (A pos = m_min; pos < m_max; pos += m_step) sum += m_f(pos) + m_f(pos + m_step);
        return sum * m_step / 2.0;
    }
};

qreal f(qreal x)
{
    return x*x*x;
}

#define MIN   qreal(-1.0 )
#define MAX   qreal( 1.0 )
#define STEP  qreal( 0.5 )
#define LEN   qreal( 1.0 )
#define INIT  qreal( 0.0 )

int main()
{
    QVector<Integrate<qreal(*)(qreal), qreal> > tasks;

    for (qreal pos = MIN; pos < MAX; pos += LEN)
        tasks.push_back(Integrate<qreal(*)(qreal), qreal>(&f, pos, pos + LEN, STEP, INIT));

    QFuture<Accumulator<qreal> > result
            = QtConcurrent::mappedReduced(tasks
                                          , &Integrate<qreal(*)(qreal), qreal>::integrate
                                          , &Accumulator<qreal>::add);
    result.waitForFinished();
    qDebug() << result.resultAt(0).value();

    return 0;
}
